# ext动态更改表格列项

# 前言

​ 因业务需要,在相同业务的表格中加多一个类型,其中对应表格某些列不一样,下面来讲讲一步步的实现思路。

# 实现

# 复制

直接复制表格改改当然比较简单,但是造成了极大的代码冗余,还要修改布局,做页面切换的逻辑。所以不考虑。

# hidden

最开始认为使用hidden属性把列隐藏就行了,后来发现在grid中,hidden是初始化的时候隐藏,用户是可以在选项中把隐藏的列显示出来的,所以这条路走不通。

# ColumnModel

查阅了EXT文档,发现grid有这个属性,可以通过它控制列。

通常我们写列时都是:

createCols : function () {
	this.columns = [
		xxx,
		xxx
	]
}

ext直接会根据this.columns去生成列。

但是还有一种写法,通过colModel

createCols : function () {
	this.colModel = new Ext.grid.ColumnModel({
		// 添加动态增删列的功能
        addColumn: function(column, colIndex){
            var config = this.config;
            this.config = [];
            if(typeof colIndex == 'number'){
                config.splice(colIndex, 0, column);
            }else{
                colIndex = config.push(column);
            }
            this.setConfig(config);
            return colIndex;
        },
        removeColumn: function(index) {
            var config = this.config;
            this.config = [];
            config.splice(index, 1);
            this.setConfig(config);
        },
        columns : [
        	xxx,
        	xxx
        ]
    })
}

根据文档的解释,colModel和columns两个属性都是必须的,猜测源码里是判断两个中存在哪个就用哪个。

通过this.config可以获取到当前列的数组,那么就可以通过修改config达到动态更改列的目的。

在切换列表类型的mgr事件中

获取grid的columnModel,其中就包含了我们写的增删列的功能函数。

删除直接传列的索引

添加传需要添加的列(跟平时写的列一样的格式)和插入位置索引。

var ColumnModel = grid.getColumnModel();

ColumnModel.removeColumn(8);
ColumnModel.addColumn({
	header : _("网络随行策略"),
	width:140,
	dataIndex : "follow_network"
}, 8);

列的全部操作结束后,通过grid的fitColumns函数,重新渲染下列,即完成了列的动态改变。

grid.getView().fitColumns();

# 优化成全局方法

上面通过columnModel实现了功能,可是扩展性不强,下面将增删的方法添加到源头去。

查看Ext.grid.GridPanel表格源代码,如下

Ext.isArray(this.columns) && (this.colModel = new Ext.grid.ColumnModel(this.columns),
        delete this.columns)

有columns时就将columns传给Ext.grid.ColumnModel

这也验证了之前的猜想。

可是增删功能是需要附在ColumnModel上的,于是通过Ext.override,给Ext.grid.GridPanel加上addColumn、removeColumn方法,然后再在执行完Ext.grid.GridPanel的initComponent后将addColumn、removeColumn添加进Ext.grid.ColumnModel中 ,这样继承自该grid的页面都拥有了增删列功能。

(function () {
    var initComponent = Ext.grid.GridPanel.prototype.initComponent;
    Ext.override(Ext.grid.GridPanel, {
        addColumn: function(column, colIndex){
            var config = this.config;
            this.config = [];
            if(typeof colIndex == 'number'){
                config.splice(colIndex, 0, column);
            }else{
                colIndex = config.push(column);
            }
            this.setConfig(config);
            return colIndex;
        },
        removeColumn: function(index) {
            var config = this.config;
            this.config = [];
            config.splice(index, 1);
            this.setConfig(config);
        },
        initComponent: function() {
            initComponent.apply(this, arguments);
            Ext.override(Ext.grid.ColumnModel, {
                addColumn: this.addColumn,
                removeColumn: this.removeColumn
            })
        }
    });
})();

之前表格的列数据也可以不用ColumnModel的形式,直接用以前的columns形式即可。

# 结语

俗话说的好:好事多磨。

不断地逼近最优解,才能实现高质量的程序。